using AuthService.Application.Services;
using AuthService.Domain.Repositories;
using AuthService.Infrastructure.Database;
using AuthService.Infrastructure.Repositories;
using AuthService.Infrastructure.Services;
using Consul;
using FluentMigrator.Runner;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Logging;

namespace AuthService.Infrastructure.Extensions;

/// <summary>
/// 服务集合扩展方法
/// 用于配置依赖注入
/// </summary>
public static class ServiceCollectionExtensions
{
    /// <summary>
    /// 添加基础设施服务
    /// </summary>
    /// <param name="services">服务集合</param>
    /// <param name="configuration">配置</param>
    /// <returns>服务集合</returns>
    public static IServiceCollection AddInfrastructure(this IServiceCollection services, IConfiguration configuration)
    {
        // 添加数据库相关服务
        services.AddDatabase(configuration);

        // 添加仓储服务
        services.AddRepositories();

        // 添加Consul服务
        services.AddConsul(configuration);

        // 添加HTTP客户端
        services.AddHttpClient();

        return services;
    }

    /// <summary>
    /// 添加应用服务
    /// </summary>
    /// <param name="services">服务集合</param>
    /// <returns>服务集合</returns>
    public static IServiceCollection AddApplication(this IServiceCollection services)
    {
        // 添加应用服务
        services.AddScoped<IDynamicApiService, DynamicApiService>();
        services.AddScoped<AuthService.Application.Services.IUserServiceSimplified, AuthService.Application.Services.UserServiceSimplified>();
        services.AddScoped<AuthService.Application.Services.IDynamicApiMappingService, AuthService.Application.Services.DynamicApiMappingService>();

        // 添加测试服务（用于验证自动发现功能）
        services.AddScoped<AuthService.Application.Services.ITestService, AuthService.Application.Services.TestService>();

        // 配置动态API映射选项
        services.Configure<AuthService.Application.Services.DynamicApiMappingOptions>(options =>
        {
            options.BasePrefix = "/api/dynamic";
            options.AutoCreateCrudEndpoints = true;
            options.RequireAuthenticationByDefault = false; // 临时禁用身份验证，方便测试
            options.DefaultRequiredRoles = new List<string> { "User" };
        });

        return services;
    }

    /// <summary>
    /// 添加数据库相关服务
    /// </summary>
    /// <param name="services">服务集合</param>
    /// <param name="configuration">配置</param>
    /// <returns>服务集合</returns>
    private static IServiceCollection AddDatabase(this IServiceCollection services, IConfiguration configuration)
    {
        var connectionString = configuration.GetConnectionString("DefaultConnection");

        if (string.IsNullOrEmpty(connectionString))
        {
            throw new InvalidOperationException("数据库连接字符串未配置");
        }

        // 添加FluentMigrator
        services.AddFluentMigratorCore()
            .ConfigureRunner(rb => rb
                .AddPostgres()
                .WithGlobalConnectionString(connectionString)
                .ScanIn(typeof(ServiceCollectionExtensions).Assembly).For.Migrations())
            .AddLogging(lb => lb.AddFluentMigratorConsole());

        // 添加迁移运行器
        services.AddScoped<AuthService.Infrastructure.Database.MigrationRunner>();

        return services;
    }

    /// <summary>
    /// 添加仓储服务
    /// </summary>
    /// <param name="services">服务集合</param>
    /// <returns>服务集合</returns>
    private static IServiceCollection AddRepositories(this IServiceCollection services)
    {
        // 注册仓储接口和实现
        services.AddScoped<IUserRepository, UserRepository>();
        services.AddScoped<IDynamicApiEndpointRepository, DynamicApiEndpointRepository>();

        return services;
    }

    /// <summary>
    /// 添加Consul服务
    /// </summary>
    /// <param name="services">服务集合</param>
    /// <param name="configuration">配置</param>
    /// <returns>服务集合</returns>
    private static IServiceCollection AddConsul(this IServiceCollection services, IConfiguration configuration)
    {
        var consulConfig = configuration.GetSection("Consul").Get<ConsulConfig>() ?? new ConsulConfig();

        // 注册Consul客户端
        services.AddSingleton<IConsulClient>(provider =>
        {
            return new ConsulClient(config =>
            {
                config.Address = new Uri(consulConfig.ConsulAddress);
                config.Datacenter = consulConfig.Datacenter;
            });
        });

        // 注册Consul服务
        services.AddSingleton<IConsulServiceRegistry, ConsulServiceRegistry>();
        services.AddSingleton<IServiceDiscoveryClient, ConsulServiceDiscoveryClient>();
        services.AddHostedService<ConsulHostedService>();

        return services;
    }

    /// <summary>
    /// 添加认证和授权
    /// </summary>
    /// <param name="services">服务集合</param>
    /// <param name="configuration">配置</param>
    /// <returns>服务集合</returns>
    public static IServiceCollection AddAuthenticationAndAuthorization(this IServiceCollection services, IConfiguration configuration)
    {
        // JWT配置
        var jwtConfig = configuration.GetSection("Jwt").Get<JwtConfig>() ?? new JwtConfig();

        services.AddAuthentication("Bearer")
            .AddJwtBearer("Bearer", options =>
            {
                options.Authority = jwtConfig.Authority;
                options.RequireHttpsMetadata = jwtConfig.RequireHttpsMetadata;
                options.Audience = jwtConfig.Audience;

                options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
                {
                    ValidateIssuer = true,
                    ValidateAudience = true,
                    ValidateLifetime = true,
                    ValidateIssuerSigningKey = true,
                    ClockSkew = TimeSpan.FromMinutes(5)
                };
            });

        services.AddAuthorization(options =>
        {
            // 添加默认策略
            options.AddPolicy("ApiAccess", policy =>
            {
                policy.RequireAuthenticatedUser();
                policy.RequireClaim("scope", "api");
            });

            // 添加管理员策略
            options.AddPolicy("AdminOnly", policy =>
            {
                policy.RequireAuthenticatedUser();
                policy.RequireRole("admin");
            });

            // 添加用户管理策略
            options.AddPolicy("UserManagement", policy =>
            {
                policy.RequireAuthenticatedUser();
                policy.RequireAssertion(context =>
                    context.User.HasClaim("permission", "user.read") ||
                    context.User.HasClaim("permission", "user.write") ||
                    context.User.IsInRole("admin"));
            });
        });

        return services;
    }

    /// <summary>
    /// 添加CORS配置
    /// </summary>
    /// <param name="services">服务集合</param>
    /// <param name="configuration">配置</param>
    /// <returns>服务集合</returns>
    public static IServiceCollection AddCorsConfiguration(this IServiceCollection services, IConfiguration configuration)
    {
        var corsConfig = configuration.GetSection("Cors").Get<CorsConfig>() ?? new CorsConfig();

        services.AddCors(options =>
        {
            options.AddPolicy("DefaultPolicy", builder =>
            {
                if (corsConfig.AllowAnyOrigin)
                {
                    builder.AllowAnyOrigin();
                }
                else
                {
                    builder.WithOrigins(corsConfig.AllowedOrigins.ToArray());
                }

                if (corsConfig.AllowAnyMethod)
                {
                    builder.AllowAnyMethod();
                }
                else
                {
                    builder.WithMethods(corsConfig.AllowedMethods.ToArray());
                }

                if (corsConfig.AllowAnyHeader)
                {
                    builder.AllowAnyHeader();
                }
                else
                {
                    builder.WithHeaders(corsConfig.AllowedHeaders.ToArray());
                }

                if (corsConfig.AllowCredentials)
                {
                    builder.AllowCredentials();
                }
            });
        });

        return services;
    }

    /// <summary>
    /// 添加API版本控制
    /// </summary>
    /// <param name="services">服务集合</param>
    /// <returns>服务集合</returns>
    public static IServiceCollection AddApiVersioning(this IServiceCollection services)
    {
        services.AddApiVersioning(options =>
        {
            options.DefaultApiVersion = new Microsoft.AspNetCore.Mvc.ApiVersion(1, 0);
            options.AssumeDefaultVersionWhenUnspecified = true;
            options.ApiVersionReader = Microsoft.AspNetCore.Mvc.Versioning.ApiVersionReader.Combine(
                new Microsoft.AspNetCore.Mvc.Versioning.QueryStringApiVersionReader("version"),
                new Microsoft.AspNetCore.Mvc.Versioning.HeaderApiVersionReader("X-Version"),
                new Microsoft.AspNetCore.Mvc.Versioning.UrlSegmentApiVersionReader()
            );
        });

        services.AddVersionedApiExplorer(options =>
        {
            options.GroupNameFormat = "'v'VVV";
            options.SubstituteApiVersionInUrl = true;
        });

        return services;
    }

    /// <summary>
    /// 添加健康检查
    /// </summary>
    /// <param name="services">服务集合</param>
    /// <param name="configuration">配置</param>
    /// <returns>服务集合</returns>
    public static IServiceCollection AddCustomHealthChecks(this IServiceCollection services, IConfiguration configuration)
    {
        services.AddHealthChecks()
            // 添加数据库健康检查
            .AddCheck<HealthChecks.DatabaseHealthCheck>("database", tags: new[] { "database", "sql" })
            // 添加Consul健康检查
            .AddCheck<HealthChecks.ConsulHealthCheck>("consul", tags: new[] { "consul", "service-discovery" })
            // 添加应用程序健康检查
            .AddCheck<HealthChecks.ApplicationHealthCheck>("application", tags: new[] { "application", "self" })
            // 添加外部依赖健康检查
            .AddCheck<HealthChecks.ExternalDependenciesHealthCheck>("external-dependencies", tags: new[] { "external", "dependencies" });

        // 注册健康检查服务
        services.AddScoped<HealthChecks.DatabaseHealthCheck>();
        services.AddScoped<HealthChecks.ConsulHealthCheck>();
        services.AddScoped<HealthChecks.ApplicationHealthCheck>();
        services.AddScoped<HealthChecks.ExternalDependenciesHealthCheck>();

        return services;
    }

    /// <summary>
    /// 添加监控和指标
    /// </summary>
    /// <param name="services">服务集合</param>
    /// <param name="configuration">配置</param>
    /// <returns>服务集合</returns>
    public static IServiceCollection AddMonitoring(this IServiceCollection services, IConfiguration configuration)
    {
        // 添加应用程序指标
        services.AddSingleton<Monitoring.IMetricsCollector, Monitoring.MetricsCollector>();
        services.AddHostedService<Monitoring.MetricsCollectionService>();

        return services;
    }
}

/// <summary>
/// JWT配置
/// </summary>
public class JwtConfig
{
    /// <summary>
    /// 颁发者
    /// </summary>
    public string Authority { get; set; } = "https://localhost:5001";

    /// <summary>
    /// 受众
    /// </summary>
    public string Audience { get; set; } = "auth-api";

    /// <summary>
    /// 是否需要HTTPS
    /// </summary>
    public bool RequireHttpsMetadata { get; set; } = true;
}

/// <summary>
/// CORS配置
/// </summary>
public class CorsConfig
{
    /// <summary>
    /// 是否允许任何来源
    /// </summary>
    public bool AllowAnyOrigin { get; set; } = false;

    /// <summary>
    /// 允许的来源列表
    /// </summary>
    public List<string> AllowedOrigins { get; set; } = new() { "https://localhost:3000" };

    /// <summary>
    /// 是否允许任何方法
    /// </summary>
    public bool AllowAnyMethod { get; set; } = true;

    /// <summary>
    /// 允许的方法列表
    /// </summary>
    public List<string> AllowedMethods { get; set; } = new() { "GET", "POST", "PUT", "DELETE", "OPTIONS" };

    /// <summary>
    /// 是否允许任何头
    /// </summary>
    public bool AllowAnyHeader { get; set; } = true;

    /// <summary>
    /// 允许的头列表
    /// </summary>
    public List<string> AllowedHeaders { get; set; } = new() { "Content-Type", "Authorization" };

    /// <summary>
    /// 是否允许凭据
    /// </summary>
    public bool AllowCredentials { get; set; } = true;
}
